Różnica między i w Javie [duplikat]

To pytanie ma już odpowiedź tutaj:

Jaka jest różnica między List<? super T> a List<? extends T>?

Kiedyś używałem List<? extends T>, ale to nie pozwala mi dodawać do niego elementów list.add(e), podczas gdy List<? super T> robi.

Author: Lonely Neuron, 2010-12-03

15 answers

extends

Deklaracja wildcard z List<? extends Number> foo3 oznacza, że każde z nich jest przypisaniem prawnym:

List<? extends Number> foo3 = new ArrayList<Number>();  // Number "extends" Number (in this context)
List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>();  // Double extends Number
  1. Czytanie - biorąc pod uwagę powyższe możliwe przydziały, jaki typ obiektu masz gwarancję odczytu z List foo3:

    • możesz przeczytać Number ponieważ każda z list, które mogą być przypisane do foo3 zawiera Number lub podklasę Number.
    • nie możesz odczytać Integer ponieważ foo3 może wskazywać na List<Double>.
    • nie możesz odczytać Double, ponieważ foo3 może wskazywać na List<Integer>.
  2. Zapis - biorąc pod uwagę powyższe możliwe zadania, jaki typ obiektu można dodać do List foo3, który byłby legalny dla wszystkich powyższych możliwychArrayList zadań:

    • nie możesz dodać Integer, ponieważ foo3 może wskazywać na List<Double>.
    • nie możesz dodać Double, ponieważ foo3 może wskazywać na List<Integer>.
    • nie możesz dodać a Number ponieważ foo3 może wskazywać na List<Integer>.

nie możesz dodać żadnego obiektu do List<? extends T>, ponieważ nie możesz zagwarantować, na jaki rodzaj List naprawdę wskazuje, więc nie możesz zagwarantować, że obiekt jest dozwolony w tym List. Jedyną "gwarancją" jest to, że możesz tylko czytać z niego i otrzymasz T lub podklasę T.

super

Zastanów się teraz List <? super T>.

Deklaracja wildcard z List<? super Integer> foo3 oznacza, że każdy z są to zadania prawne:

List<? super Integer> foo3 = new ArrayList<Integer>();  // Integer is a "superclass" of Integer (in this context)
List<? super Integer> foo3 = new ArrayList<Number>();   // Number is a superclass of Integer
List<? super Integer> foo3 = new ArrayList<Object>();   // Object is a superclass of Integer
  1. Czytanie - biorąc pod uwagę powyższe możliwe przydziały, jaki typ obiektu masz gwarancję otrzymania po przeczytaniu z List foo3:

    • nie masz gwarancji Integer, ponieważ foo3 może wskazywać na List<Number> lub List<Object>.
    • nie masz gwarancji Number ponieważ foo3 może wskazywać na List<Object>.
    • jedyną gwarancją jest to, że otrzymasz instancję Object lub podklasa Object (ale nie wiesz jaka podklasa).
  2. Zapis - biorąc pod uwagę powyższe możliwe zadania, jaki typ obiektu można dodać do List foo3, który byłby legalny dla wszystkich powyższych możliwychArrayList zadań:

    • możesz dodać Integer, ponieważ Integer jest dozwolone w dowolnej z powyższych list.
    • możesz dodać instancję podklasy Integer, ponieważ instancja podklasy Integer jest dozwolona w którymkolwiek z powyższych listy.
    • nie możesz dodać Double, ponieważ foo3 może wskazywać na ArrayList<Integer>.
    • nie możesz dodać Number, ponieważ foo3 może wskazywać na ArrayList<Integer>.
    • nie możesz dodać Object, ponieważ foo3 może wskazywać na ArrayList<Integer>.

PECS

Remember PECS: "producent rozszerza, konsument Super" .

  • "Producer Extends" - jeśli potrzebujesz List do wytworzenia T wartości (chcesz odczytać T s z listy), należy ją zadeklarować za pomocą ? extends T, np. List<? extends Integer>. Ale nie możesz dodać do tej listy.

  • "Consumer Super" - jeśli potrzebujesz List do pochłonięcia Twartości (chcesz zapisać T s na liście), musisz zadeklarować ją za pomocą ? super T, np. List<? super Integer>. Nie ma jednak gwarancji, jakiego typu obiekt można odczytać z tej listy.

  • Jeśli potrzebujesz zarówno odczytu z listy, jak i zapisu na listę, musisz zadeklarować ją dokładnie bez wildcards, np. List<Integer>.

Przykład

Uwaga ten przykład z Java Generics FAQ. Uwaga: lista źródłowa src (lista produkcyjna) używa extends, a lista docelowa dest (lista konsumująca) używa super:

public class Collections { 
  public static <T> void copy(List<? super T> dest, List<? extends T> src) {
      for (int i = 0; i < src.size(); i++) 
        dest.set(i, src.get(i)); 
  } 
}

Zobacz też jak Mogę dodać do listy rozszerza numer > struktury danych?

 1142
Author: Bert F,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-07 05:21:18

Wyobraź sobie, że masz taką hierarchię

Tutaj wpisz opis obrazka

1. Extends

Pisząc

    List<? extends C2> list;

Mówisz, że list będzie w stanie odwołać się do obiektu typu (na przykład) ArrayList, którego typ ogólny jest jednym z 7 podtypów Z C2 (C2 włączone):

  1. C2: new ArrayList<C2>();, (obiekt, który może przechowywać C2 lub podtypy) lub
  2. D1: new ArrayList<D1>();, (obiekt, który może przechowywać D1 lub podtypy) lub
  3. D2: new ArrayList<D2>();, (obiekt, który może przechowywać D2 lub podtypy) lub...

I tak dalej. Siedem różnych przypadków:

    1) new ArrayList<C2>(): can store C2 D1 D2 E1 E2 E3 E4
    2) new ArrayList<D1>(): can store    D1    E1 E2  
    3) new ArrayList<D2>(): can store       D2       E3 E4
    4) new ArrayList<E1>(): can store          E1             
    5) new ArrayList<E2>(): can store             E2             
    6) new ArrayList<E3>(): can store                E3             
    7) new ArrayList<E4>(): can store                   E4             

Mamy zbiór typów "przechowywalnych" dla każdego możliwego przypadku: 7 (czerwonych) zestawów tutaj przedstawianych graficznie

Tutaj wpisz opis obrazka

Jak widzisz, nie ma bezpiecznego typu , który jest wspólny dla każdego przypadku:

  • nie możesz list.add(new C2(){}); ponieważ może być list = new ArrayList<D1>();
  • nie możesz list.add(new D1(){}); ponieważ może być list = new ArrayList<D2>();

I tak dalej.

2. Super

Pisząc

    List<? super C2> list;

Mówisz, że list będzie w stanie odwołać się do obiektu typu (na przykład) ArrayList, którego typ ogólny jest jednym z 7supertypów Z C2 (C2 włączone):

  • A1: new ArrayList<A1>();, (obiekt, który może przechowywać A1 lub podtypy) lub
  • A2: new ArrayList<A2>();, (obiekt, który może przechowywać A2 lub podtypy) lub
  • A3: new ArrayList<A3>();, (obiekt, który może przechowywać A3 lub podtypy) lub...

I tak dalej. Siedem różnych przypadków:

    1) new ArrayList<A1>(): can store A1          B1 B2       C1 C2    D1 D2 E1 E2 E3 E4
    2) new ArrayList<A2>(): can store    A2          B2       C1 C2    D1 D2 E1 E2 E3 E4
    3) new ArrayList<A3>(): can store       A3          B3       C2 C3 D1 D2 E1 E2 E3 E4
    4) new ArrayList<A4>(): can store          A4       B3 B4    C2 C3 D1 D2 E1 E2 E3 E4
    5) new ArrayList<B2>(): can store                B2       C1 C2    D1 D2 E1 E2 E3 E4
    6) new ArrayList<B3>(): can store                   B3       C2 C3 D1 D2 E1 E2 E3 E4
    7) new ArrayList<C2>(): can store                            C2    D1 D2 E1 E2 E3 E4

Mamy zbiór typów "przechowywalnych" dla każdego możliwego przypadku: 7 (czerwonych) zestawów tutaj przedstawianych graficznie

Tutaj wpisz opis obrazka

Jak widzisz, tutaj mamy siedem bezpiecznych typów , które są wspólne dla każdej sprawy: C2, D1, D2, E1, E2, E3, E4.

  • możesz list.add(new C2(){}); ponieważ, niezależnie od rodzaju listy jesteśmy odsyłacze, C2 jest dozwolone
  • możesz list.add(new D1(){}); ponieważ, niezależnie od rodzaju listy, do której się odwołujemy, D1 jest dozwolone

I tak dalej. Prawdopodobnie zauważyłeś, że te typy odpowiadają hierarchii zaczynającej się od type C2.

Uwagi

Tutaj pełna hierarchia, jeśli chcesz wykonać kilka testów

interface A1{}
interface A2{}
interface A3{}
interface A4{}

interface B1 extends A1{}
interface B2 extends A1,A2{}
interface B3 extends A3,A4{}
interface B4 extends A4{}

interface C1 extends B2{}
interface C2 extends B2,B3{}
interface C3 extends B3{}

interface D1 extends C1,C2{}
interface D2 extends C2{}

interface E1 extends D1{}
interface E2 extends D1{}
interface E3 extends D2{}
interface E4 extends D2{}
 177
Author: Luigi Cortese,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-15 13:51:29

Podoba mi się odpowiedź od @ Bert F, ale tak to postrzega mój mózg.

Mam X w ręku. Jeśli chcę zapisać moje X na Listę, Ta lista musi być albo listą X lub listą rzeczy, do których moje X może być upcast tak, jak je piszę, tj. Dowolna superclass z X...

List<? super   X>

Jeśli dostanę listę i chcę odczytać X z tej listy, to lepiej będzie lista X lub lista rzeczy, które mogą być upcast do X jak je odczytam, tzn. cokolwiek że rozszerza X

List<? extends X>
Mam nadzieję, że to pomoże.
 60
Author: Michael Dausmann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-03 22:05:16

Na podstawie odpowiedzi Berta F {[20] } chciałbym wyjaśnić moje zrozumienie.

Powiedzmy, że mamy 3 klasy jako

public class Fruit{}

public class Melon extends Fruit{}

public class WaterMelon extends Melon{}

Tutaj mamy

List<? extends Fruit> fruitExtendedList = …

//Says that I can be a list of any object as long as this object extends Fruit.

Ok teraz spróbujmy uzyskać jakąś wartość z fruitExtendedList

Fruit fruit = fruitExtendedList.get(position)

//This is valid as it can only return Fruit or its subclass.

Jeszcze raz spróbujmy

Melon melon = fruitExtendedList.get(position)

//This is not valid because fruitExtendedList can be a list of Fruit only, it may not be 
//list of Melon or WaterMelon and in java we cannot assign sub class object to 
//super class object reference without explicitly casting it.

Tak samo jest w przypadku

WaterMelon waterMelon = fruitExtendedList.get(position)

Teraz spróbujmy ustawić jakiś obiekt w fruitExtendedList

Dodawanie obiektu owoców

fruitExtendedList.add(new Fruit())

//This in not valid because as we know fruitExtendedList can be a list of any 
//object as long as this object extends Fruit. So what if it was the list of  
//WaterMelon or Melon you cannot add Fruit to the list of WaterMelon or Melon.

Dodawanie obiektu Melon

fruitExtendedList.add(new Melon())

//This would be valid if fruitExtendedList was the list of Fruit but it may 
//not be, as it can also be the list of WaterMelon object. So, we see an invalid 
//condition already.

Wreszcie niech spróbuj dodać obiekt arbuza

fruitExtendedList.add(new WaterMelon())

//Ok, we got it now we can finally write to fruitExtendedList as WaterMelon 
//can be added to the list of Fruit or Melon as any superclass reference can point 
//to its subclass object.

ale czekaj co jeśli ktoś zdecyduje się zrobić nowy rodzaj cytryny powiedzmy dla argumentów sake SaltyLemon jako

public class SaltyLemon extends Lemon{}

teraz fruitExtendedList może być lista owoców, Melon, arbuz lub SaltyLemon.

Więc nasza wypowiedź

fruitExtendedList.add(new WaterMelon())

Również nie jest poprawna.

Zasadniczo możemy powiedzieć, że nie możemy nic napisać do fruitExtendedList.

To podsumowuje List<? extends Fruit>

Teraz zobaczmy

List<? super Melon> melonSuperList= …

//Says that I can be a list of anything as long as its object has super class of Melon.

Teraz spróbujmy uzyskać jakąś wartość z melonSuperList

Fruit fruit = melonSuperList.get(position)

//This is not valid as melonSuperList can be a list of Object as in java all 
//the object extends from Object class. So, Object can be super class of Melon and 
//melonSuperList can be a list of Object type

podobnie nie można odczytać melona, arbuza ani żadnego innego obiektu.

Ale zauważ, że możemy odczytywać instancje typu obiektu

Object myObject = melonSuperList.get(position)

//This is valid because Object cannot have any super class and above statement 
//can return only Fruit, Melon, WaterMelon or Object they all can be referenced by
//Object type reference.

Teraz spróbujmy ustawić jakąś wartość z melonSuperList.

Dodawanie obiektu typu object

melonSuperList.add(new Object())

//This is not valid as melonSuperList can be a list of Fruit or Melon.
//Note that Melon itself can be considered as super class of Melon.

Dodawanie obiektu typu owoce

melonSuperList.add(new Fruit())

//This is also not valid as melonSuperList can be list of Melon

Dodanie rodzaju melona obiekt

melonSuperList.add(new Melon())

//This is valid because melonSuperList can be list of Object, Fruit or Melon and in 
//this entire list we can add Melon type object.

Dodawanie obiektu typu arbuz

melonSuperList.add(new WaterMelon())

//This is also valid because of same reason as adding Melon

Podsumowując możemy dodać Melon lub jego podklasę do melonSuperList i tylko do odczytu obiekt typu object.

 17
Author: Sushant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:36

Super to dolna granica, a extends to górna granica.

Zgodnie z http://download.oracle.com/javase/tutorial/extra/generics/morefun.html :

Rozwiązaniem jest użycie formy bounded wildcard we haven ' t seen yet: wildcards z dolną krawędzią. Na składnia ? super T oznacza nieznany typ, który jest supertyp T (lub T siebie; pamiętaj, że supertyp relacja jest refleksyjna). Jest to podwójny of the bounded wildcards we ' ve been za pomocą, gdzie używamy ? rozszerza T do oznacza Nieznany typ, który jest Podtyp T.

 14
Author: Istao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-03 07:04:21

Używając extends można uzyskać tylko z kolekcji. Nie możesz tego włożyć. Ponadto, chociaż super pozwala zarówno na get, jak i put, typ zwracany podczas get to ? super T .

 3
Author: Sai Sunder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-04 22:36:39

Najbardziej mylące jest to, że niezależnie od ograniczeń typu, które określimy, przypisanie działa tylko w jeden sposób: {]}

baseClassInstance = derivedClassInstance;

Możesz myśleć, że Integer extends Number i że Integer zrobiłby to jako <? extends Number>, ale kompilator powie Ci, że <? extends Number> cannot be converted to Integer (to znaczy, w ludzkim mowie, jest złe, że wszystko, co rozszerza liczbę, może być zamienione na liczbę całkowitą):

class Holder<T> {
    T v;
    T get() { return v; }
    void set(T n) { v=n; }
}
class A {
    public static void main(String[]args) {
        Holder<? extends Number> he = new Holder();
        Holder<? super Number> hs = new Holder();

        Integer i;
        Number n;
        Object o;

        // Producer Super: always gives an error except
        //       when consumer expects just Object
        i = hs.get(); // <? super Number> cannot be converted to Integer
        n = hs.get(); // <? super Number> cannot be converted to Number
                      // <? super Number> cannot be converted to ... (but
                      //       there is no class between Number and Object)
        o = hs.get();

        // Consumer Super
        hs.set(i);
        hs.set(n);
        hs.set(o); // Object cannot be converted to <? super Number>

        // Producer Extends
        i = he.get(); // <? extends Number> cannot be converted to Integer
        n = he.get();
        o = he.get();

        // Consumer Extends: always gives an error
        he.set(i); // Integer cannot be converted to <? extends Number>
        he.set(n); // Number cannot be converted to <? extends Number>
        he.set(o); // Object cannot be converted to <? extends Number>
    }
}

hs.set(i); jest ok bo Integer można przekonwertować do dowolnej klasy superklasy Number (i nie dlatego, że Integer jest superclass of Number, co nie jest prawdą).

EDIT dodał komentarz o Consumer Extends i Producer Super -- nie są one znaczące, ponieważ określają odpowiednio nic i tylko Object. Zaleca się, aby pamiętać PECS, ponieważ CEPS nigdy nie jest przydatne.

 2
Author: 18446744073709551615,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-26 11:03:56

Ogólne symbole wieloznaczne są adresowane do dwóch podstawowych potrzeb:

Czytanie ze zbioru ogólnego Wstawianie do zbioru generycznego Istnieją trzy sposoby definiowania kolekcji (zmiennej) za pomocą ogólnych symboli wieloznacznych. Są to:

List<?>           listUknown = new ArrayList<A>();
List<? extends A> listUknown = new ArrayList<A>();
List<? super   A> listUknown = new ArrayList<A>();

List<?> oznacza listę wpisaną do nieznanego typu. Może to być List<A>, a List<B>, a List<String> itd.

List<? extends A> oznacza listę obiektów będących instancjami class A lub subclasses of A (np. B I C). List<? super A> oznacza, że lista jest wpisywana do A class, lub superclass of A.

Czytaj więcej: http://tutorials.jenkov.com/java-generics/wildcards.html

 1
Author: Vaibhav Gupta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-23 13:25:09

Kiedy używać rozszerzeń i super

Symbole wieloznaczne są najbardziej przydatne w parametrach metod. Pozwalają one na niezbędną elastyczność w interfejsach metod.

Ludzie często są zdezorientowani, kiedy używać rozszerzeń, a kiedy superbohaterów. Zasadą jest zasada get-put. Jeśli otrzymujesz coś z parametryzowanego kontenera, użyj extends.

int totalFuel(List<? extends Vehicle> list) {
int total = 0;
for(Vehicle v : list) {
    total += v.getFuel();
}
return total;}
Metoda totalFuel pobiera Pojazdy z listy, pyta je o ilość paliwa i oblicza całość. Jeśli umieścisz obiekty w sparametryzowanym kontenerze, Użyj super.
int totalValue(Valuer<? super Vehicle> valuer) {
int total = 0;
for(Vehicle v : vehicles) {
    total += valuer.evaluate(v);
}
return total;}

Metoda totalValue umieszcza pojazdy w rzeczoznawcy. Warto wiedzieć, że extends bound jest znacznie bardziej powszechny niż super.

 1
Author: Kevin STS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-01 22:20:38

Możesz przejść przez wszystkie powyższe odpowiedzi, aby zrozumieć, dlaczego {[0] } jest ograniczony do '<?>', '<? extends>', i częściowo do '<? super>'.

Ale oto podsumowanie tego wszystkiego, jeśli chcesz o tym pamiętać i nie chcesz za każdym razem odkrywać odpowiedzi:

List<? extends A> oznacza, że będzie to akceptować dowolną List z A i podklasę A. Ale nie możesz nic dodać do tej listy. Nawet obiektów typu A.

List<? super A> oznacza, że będzie to akceptować dowolną listę A i superklasę A. Możesz dodawać obiekty typu A i jego podklasy.

 1
Author: jforex78,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-14 10:37:29

Głosowane odpowiedzi obejmują szczegóły dotyczące wielu aspektów. Postaram się jednak odpowiedzieć na to w inny sposób.

Są 2 rzeczy, które musimy rozważyć,

1. Przypisanie do zmiennej listy

List<? extends X> listvar;

Tutaj Dowolna lista X lub lista podklas X może być przypisana do listvar.

List<? extends Number> listvar; listvar = new ArrayList<Number>(); listvar = new ArrayList<Integer>();


List<? super X> listvar;

Tutaj Dowolna lista X lub lista superklas X może być przypisana do listvar.

List<? super Number> listvar; listvar = new ArrayList<Number>(); listvar = new ArrayList<Object>();

2. Wykonywanie operacji odczytu lub zapisu na zmiennej list

`List<? extends X> listvar;`

Możesz użyć tej funkcji, aby zaakceptować listę w argumentach metody i wykonać dowolne operacje na typu X (Uwaga: możesz odczytywać tylko obiekty typu X z listy).

`List<? super Number> listvar;

Możesz użyć tej funkcji, aby zaakceptować listę w argumentach metody i wykonać dowolne operacje na obiekcie typu , ponieważ możesz odczytywać tylko obiekty typu Object z lista. ale tak, dodatkową rzeczą jest to, że możesz dodawać obiekty typu X do listy.

 1
Author: Shailesh Pratapwar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-31 04:20:18

Lista nie pozwala dodawać do listy niczego poza null.

Lista pozwala dodać wszystko, co jest-X (X lub jego podklasa), lub null.

 1
Author: elyor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-07 12:24:45

Chciałbym wyobrazić sobie różnicę. Załóżmy, że mamy:

class A { }
class B extends A { }
class C extends B { }

List<? extends T> - czytanie i przypisywanie:

|-------------------------|-------------------|---------------------------------|
|         wildcard        |        get        |              assign             |
|-------------------------|-------------------|---------------------------------|
|    List<? extends C>    |    A    B    C    |   List<C>                       |
|-------------------------|-------------------|---------------------------------|
|    List<? extends B>    |    A    B         |   List<B>   List<C>             |
|-------------------------|-------------------|---------------------------------|
|    List<? extends A>    |    A              |   List<A>   List<B>   List<C>   |
|-------------------------|-------------------|---------------------------------|

List<? super T> - zapis i przypisanie:

|-------------------------|-------------------|--------------------------------------------|
|         wildcard        |        add        |                   assign                   |
|-------------------------|-------------------|--------------------------------------------|
|     List<? super C>     |    C              |  List<Object>  List<A>  List<B>   List<C>  |
|-------------------------|-------------------|--------------------------------------------|
|     List<? super B>     |    B    C         |  List<Object>  List<A>  List<B>            |
|-------------------------|-------------------|--------------------------------------------|
|     List<? super A>     |    A    B    C    |  List<Object>  List<A>                     |
|-------------------------|-------------------|--------------------------------------------|

We wszystkich przypadkach:

  • zawsze możesz dostać Object z listy niezależnie od symbolu wildcard.
  • zawsze możesz dodać null do listy mutowalnej niezależnie od symbolu wildcard.
 1
Author: Oleksandr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-23 17:46:55
                                       |
                                       v

Lista ? może być dowolną podklasą z X lub samą X.

Lista ? może być dowolną superklasą z X lub samą X.

                                      ^
                                      |
 0
Author: snr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-11 07:35:35

Przykład, Kolejność dziedziczenia przyjmuje się jako O > S > T > U > V

Użycie słowa kluczowego extends,

poprawne:

List<? extends T> Object = new List<T>();
List<? extends T> Object = new List<U>();
List<? extends T> Object = new List<V>();

niepoprawne:

List<? extends T> Object = new List<S>();
List<? extends T> Object = new List<O>();

Super Słowo Kluczowe:

poprawne:

List<? super T> Object = new List<T>();
List<? super T> Object = new List<S>();
List<? super T> Object = new List<O>();

niepoprawne:

List<? super T> Object = new List<U>();
List<? super T> Object = new List<V>();

Dodawanie obiektu: List Object = new List ();

Object.add(new T()); //error

Ale dlaczego błąd ? Przyjrzyjmy się możliwościom inicjalizacja obiektu List

List<? extends T> Object = new List<T>();
List<? extends T> Object = new List<U>();
List<? extends T> Object = new List<V>();

Jeśli użyjemy Object.add (new t ()); wtedy będzie poprawne tylko jeżeli

List<? extends T> Object = new List<T>(); 

Ale są dwie dodatkowe możliwości

List Object = new List(); List Object = new List(); Jeśli spróbujemy dodać (new t ()) do powyższych dwóch możliwości, da to błąd, ponieważ T jest klasą nadrzędną U i V. staramy się dodać obiekt T [czyli (new t ())] do listy typu U I V . Obiekt wyższej klasy (klasa bazowa) nie może zostać przekazany do niższej klasy Obiekt(podklasa).

Ze względu na dodatkowe dwie możliwości, Java daje błąd, nawet jeśli używasz poprawnej możliwości, ponieważ Java nie wie, do jakiego obiektu się odnosisz .więc nie możesz dodawać obiektów do listy Object = new List (); ponieważ istnieją możliwości, które nie są poprawne.

Dodawanie obiektu: List Object = new List ();

Object.add(new T()); // compiles fine without error
Object.add(new U()); // compiles fine without error
Object.add(new V()); // compiles fine without error

Object.add(new S()); //  error
Object.add(new O()); //  error

Ale dlaczego błąd występuje w dwóch powyższych ? możemy użyć obiektu.add (new t ()); tylko na poniższych możliwościach,

List<? super T> Object = new List<T>();
List<? super T> Object = new List<S>();
List<? super T> Object = new List<O>();

Jeśli spróbujemy użyć Obiekt.add (new T ()) in List Object = new List(); oraz List Object = new List(); wtedy to da błąd Dzieje się tak dlatego, że Nie możemy dodać obiektu T [który jest new t()] do listy Object = new List (); ponieważ jest to obiekt typu U . Nie możemy dodać obiektu T [który jest nową T()] do obiektu U, ponieważ T jest klasą bazową, a U podklasą . Nie możemy dodać klasy bazowej do podklasy i dlatego występuje błąd . To samo dotyczy innej sprawy .

 -1
Author: Crox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-22 17:57:34